package gapidt.plugin.wizards;

import gapidt.common.Locale;
import gapidt.nlp.SemanticUtils;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.preference.FileFieldEditor;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TouchEvent;
import org.eclipse.swt.events.TouchListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.dialogs.ContainerSelectionDialog;
import org.eclipse.ui.dialogs.FileSelectionDialog;
import org.eclipse.ui.dialogs.ResourceSelectionDialog;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.eclipse.ui.internal.IPreferenceConstants;

/**
 * The "New" wizard page allows setting the container for the new file as well
 * as the file name. The page will only accept file name without the extension
 * OR with the extension that matches the expected one (mpe).
 */

public class WsdlGeneratorPage2 extends WizardPage {
	
	private Text schemaFileText;
	private Text schemaFileContainerText;
	private Button schemaFileContainerButton;
	private Text schemaTargetNamespaceText;
	private Text schemaPublicUrlText;
	private Button enclosedSchemaCheckbox;
	private Button notEnclosedSchemaCheckbox;
	
	private IType[] types;
	private IJavaProject javaProject;

	/**
	 * Constructor for SampleNewWizardPage.
	 * 
	 * @param pageName
	 */
	public WsdlGeneratorPage2(IType[] types, IJavaProject javaProject) {
		super("wsdlGeneratorPage2");
		setTitle(Locale.getMessage("gapidt.plugin.wizards.WsdlGeneratorWizard.title"));
		setDescription(Locale.getMessage("gapidt.plugin.wizards.WsdlGeneratorWizard.description"));
		this.types = types;
		this.javaProject = javaProject;
	}

	/**
	 * @see IDialogPage#createControl(Composite)
	 */
	public void createControl(Composite parent) {
		Composite container = new Composite(parent, SWT.NULL);
		
		//Create layout
		GridLayout layout = new GridLayout();
		container.setLayout(layout);

		layout.numColumns = 1;
		layout.verticalSpacing = 9;
		
		Label label = new Label(container, SWT.NULL);
		label.setText("&"+Locale.getMessage("data_types_config")+":");

		Composite tnsContainer = new Composite(container, SWT.NULL);
		GridLayout tnsLayout = new GridLayout();
		tnsContainer.setLayout(tnsLayout);
		tnsContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		tnsLayout.numColumns = 2;
		tnsLayout.verticalSpacing = 9;
		
		//Schema target namespace
		label = new Label(tnsContainer, SWT.NULL);
		label.setText("&"+Locale.getMessage("target_ns")+":");
	
		schemaTargetNamespaceText = new Text(tnsContainer, SWT.BORDER | SWT.SINGLE);
		schemaTargetNamespaceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		schemaTargetNamespaceText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		// Create the first group
		Group group = new Group(container, SWT.NULL);
	    group.setText(Locale.getMessage("data_types"));
	    group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
	    
	    GridLayout groupLayout = new GridLayout();
	    groupLayout.numColumns = 1;
	    groupLayout.verticalSpacing = 5;
	    group.setLayout(groupLayout);
	    
	    enclosedSchemaCheckbox = new Button(group, SWT.RADIO);
	    enclosedSchemaCheckbox.setText(Locale.getMessage("enclosed_data_types"));
	    enclosedSchemaCheckbox.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				dialogChanged();
			}
		});
	    
	    notEnclosedSchemaCheckbox = new Button(group, SWT.RADIO);
	    notEnclosedSchemaCheckbox.setText(Locale.getMessage("not_enclosed_data_types"));
	    notEnclosedSchemaCheckbox.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				dialogChanged();
			}
		});
		
		Composite schemaContainer = new Composite(group, SWT.NULL);
		schemaContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		GridLayout schemaLayout = new GridLayout();
		schemaContainer.setLayout(schemaLayout);
		schemaLayout.numColumns = 3;
		schemaLayout.verticalSpacing = 2;
		schemaLayout.horizontalSpacing = 5;
		
		//Schema file name
		label = new Label(schemaContainer, SWT.NULL);
		label.setText("&"+Locale.getMessage("file_name")+":");

		schemaFileText = new Text(schemaContainer, SWT.BORDER | SWT.SINGLE);
		schemaFileText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		schemaFileText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		(new Label(schemaContainer, SWT.NULL)).setText("");
		
		label = new Label(schemaContainer, SWT.NULL);
		label.setText("&"+Locale.getMessage("container")+":");
		
		schemaFileContainerText = new Text(schemaContainer, SWT.BORDER | SWT.SINGLE);
		schemaFileContainerText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		schemaFileContainerText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		schemaFileContainerButton = new Button(schemaContainer, SWT.PUSH);
		schemaFileContainerButton.setText(Locale.getMessage("browse")+"...");
		schemaFileContainerButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				handleContainerBrowse(schemaFileContainerText, Locale.getMessage("select_container"));
			}
		});
		
		//Schema public location
		label = new Label(schemaContainer, SWT.NULL);
		label.setText("&"+Locale.getMessage("public_url")+":");

		schemaPublicUrlText = new Text(schemaContainer, SWT.BORDER | SWT.SINGLE);
		schemaPublicUrlText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		schemaPublicUrlText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});
		
		(new Label(schemaContainer, SWT.NULL)).setText("");
		
		initialize();
		dialogChanged();
		setControl(container);
	}

	/**
	 * Tests if the current workbench selection is a suitable container to use.
	 */
	private void initialize() {
		if (types != null && types.length > 0) {
			
			IContainer container = types[0].getCompilationUnit().getResource().getParent();
			
			enclosedSchemaCheckbox.setSelection(true);
			schemaFileContainerText.setText(container.getFullPath().toString());
			
			String schemaFileName = "services";
			schemaFileText.setText(schemaFileName+".xsd");
			schemaTargetNamespaceText.setText("http://example.com/"+schemaFileName+"/schemas");
			schemaPublicUrlText.setText("http://example.com/"+schemaFileName+".xsd");
		}else{
			schemaFileText.setText("services.xsd");
		}
	}

	/**
	 * Uses the standard container selection dialog to choose the new value for
	 * the container field.
	 */
	private void handleContainerBrowse(Text textElement, String dialogTitle){
		ContainerSelectionDialog dialog = new ContainerSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(), false, dialogTitle);
		
		if (dialog.open() == ContainerSelectionDialog.OK) {
			Object[] result = dialog.getResult();
			if (result.length == 1)
				textElement.setText(((Path) result[0]).toString());
		}
	}
	
	/**
	 * Ensures that both text fields are set.
	 */

	private void dialogChanged() {
		IResource container = ResourcesPlugin.getWorkspace().getRoot()
				.findMember(new Path(getSchemaFileContainerName()));
		
		if(!validTargetNamespace(schemaTargetNamespaceText, "schema_target_ns"))
			return;

		if (getSchemaFileContainerName().length() == 0) {
			updateStatus(Locale.getMessage("container_empty"));
			return;
		}
		if (container == null || (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) {
			updateStatus(Locale.getMessage("container_not_found"));
			return;
		}
		if (!container.isAccessible()) {
			updateStatus(Locale.getMessage("container_not_writable"));
			return;
		}
		
		if(!getEnclosedSchema()){
			schemaFileText.setEnabled(true);
			schemaFileContainerText.setEnabled(true);
			schemaFileContainerButton.setEnabled(true);
			schemaPublicUrlText.setEnabled(true);
			if(!validFileName(schemaFileText, "xsd", "schema_file"))
				return;
			if(!validUrl(schemaPublicUrlText, "schema_public_url"))
				return;
		}else{
			schemaFileText.setEnabled(false);
			schemaFileContainerText.setEnabled(false);
			schemaFileContainerButton.setEnabled(false);
			schemaPublicUrlText.setEnabled(false);
		}
		
		updateStatus(null);
	}

	private void updateStatus(String message) {
		setErrorMessage(message);
		setPageComplete(message == null);
	}

	public String getSchemaFileName() {
		if(schemaFileText != null)
			return schemaFileText.getText();
		return "";
	}
	
	public String getSchemaFileContainerName() {
		if(schemaFileContainerText != null)
			return schemaFileContainerText.getText();
		return "";
	}
	
	public String getSchemaTargetNamespace() {
		if(schemaTargetNamespaceText != null)
			return schemaTargetNamespaceText.getText();
		return "";
	}
	
	public String getSchemaPublicUrl() {
		if(schemaPublicUrlText != null)
			return schemaPublicUrlText.getText();
		return "";
	}
	
	public boolean getEnclosedSchema(){
		if(enclosedSchemaCheckbox != null)
			return enclosedSchemaCheckbox.getSelection();
		return true;
	}
	
	public void setSeparatedSchemaEnabled(boolean enabled){
		if(notEnclosedSchemaCheckbox != null)
			if(enabled)
				notEnclosedSchemaCheckbox.setEnabled(true);
			else
				notEnclosedSchemaCheckbox.setEnabled(false);
	}
	
	public void setTargetNamespaceEnabled(boolean enabled){
		if(schemaTargetNamespaceText != null)
			if(enabled)
				schemaTargetNamespaceText.setEnabled(true);
			else
				schemaTargetNamespaceText.setEnabled(false);
	}
	
	public boolean validFileName(Text textInput, String extension, String inputKey){
		String value = textInput.getText();
		if (value.length() == 0) {
			updateStatus(Locale.getMessage(inputKey+"_empty"));
			return false;
		}
		if (value.replace('\\', '/').indexOf('/', 1) > 0) {
			updateStatus(Locale.getMessage(inputKey+"_invalid"));
			return false;
		}
		int dotLoc = value.lastIndexOf('.');
		String ext = value.substring(dotLoc + 1);
		if (dotLoc == -1) ext = "";
		if (ext.equalsIgnoreCase(extension) == false) {
			updateStatus(Locale.getMessage(inputKey+"_wrong_extension"));
			return false;
		}
		return true;
	}
	
	public boolean validTargetNamespace(Text textInput, String inputKey){
		String value = textInput.getText();
		if (value.length() == 0) {
			updateStatus(Locale.getMessage(inputKey+"_empty"));
			return false;
		}
		return true;
	}
	
	public boolean validUrl(Text textInput, String inputKey){
		String value = textInput.getText();
		if (value.length() == 0) {
			updateStatus(Locale.getMessage(inputKey+"_empty"));
			return false;
		}
		return true;
	}
}